home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / Q-R / RIFF File Format / RIFFoutput.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-09-15  |  6.7 KB  |  258 lines  |  [TEXT/KAHL]

  1. /*
  2. MOD 08-07-87 MAZ - fix clobber of "i" within chunks loop that caused infinite writes
  3. MOD 07-12-87 MAZ - file converter RIFF output routines
  4. */
  5. #include <Quickdraw.h>
  6. #include <WindowMgr.h>
  7. #include <EventMgr.h>
  8. #include <MenuMgr.h>
  9. #include <ControlMgr.h>
  10. #include <DialogMgr.h>
  11. #include <FileMgr.h>
  12. #include <StdFilePkg.h>
  13. #include "MAZlib.h"
  14. #include "RIFF.h"
  15.  
  16. extern bool init_io();
  17.  
  18. /* MAZlib externs */
  19. extern bool output_file_name();
  20. extern short global_volrefnum;
  21. extern long disk_bytes_free();
  22.  
  23. /* the stuff read in */
  24. extern unsigned char *body[4];
  25. extern short nrows;
  26. extern short ncols;
  27. extern short nsamples;
  28. extern short storage_type;
  29. extern short dpi;
  30. extern bool uncompressed;
  31. extern unsigned char *transfer_table;
  32.  
  33. /* globals for custom standard file dialogs */
  34. SFTypeList otherTypeList;
  35.  
  36. /* forward declarations */
  37. short save_open();
  38. short save_data();
  39.  
  40. /* save picture to prompted name */
  41. bool save_as_RIFF(suggested, desired_nsamples)
  42. char *suggested;
  43. short desired_nsamples;
  44.     {
  45.     short i;
  46.     char filename[256];
  47.  
  48.     while (output_file_name("Save As:", filename, suggested))
  49.         {
  50.         strcpy(suggested, filename);
  51.         /* do the save */
  52.         i = save_data(global_volrefnum, filename, desired_nsamples);
  53.         /* and exit if all went well */
  54.         if (i == 0)
  55.             return(true);
  56.         /* not enough memory to allocate buffers for save */
  57.         /* user doesn't get another chance to do it */
  58.         if (i == 3)
  59.             return(false);
  60.         /* otherwise, try again... */
  61.         }
  62.     /* user cancelled */
  63.     return(false);
  64.     }
  65.  
  66. /* open RIFF file for writing */
  67. static short save_open(refnum, filename, bytecount, io)
  68. short refnum;
  69. char *filename;
  70. long bytecount;
  71. ioParam *io;
  72.     {
  73.     bool save_finder_info;
  74.     FileParam fparm;
  75.  
  76.     /* get Pascal filename */
  77.     CtoPstr(filename);
  78.     /* get info on existing output file of same name (if any) */
  79.     fparm.ioNamePtr = (StringPtr)filename;
  80.     fparm.ioVRefNum = refnum;
  81.     fparm.ioFVersNum = 0;        /* normal version */
  82.     fparm.ioFDirIndex = 0;        /* use filename and vrefnum */
  83.     fparm.ioResult = 1;
  84.     PBGetFInfo(&fparm, false);
  85.     if (fparm.ioResult >= 0)
  86.         {
  87.         /* file exists, reduce bytecount needed by its size */
  88.         bytecount -= fparm.ioFlPyLen;
  89.         /* save old file's finder info if the same type */
  90.         save_finder_info = (fparm.ioFlFndrInfo.fdType == 'RIFF' &&
  91.           fparm.ioFlFndrInfo.fdCreator == 'FSPE');
  92.         }
  93.     else
  94.         save_finder_info = false;
  95.     /* make sure there is enough room on disk for file */
  96.     if (bytecount > disk_bytes_free(refnum))
  97.         {
  98.         /* undo damage to filename */
  99.         PtoCstr(filename);
  100.         return(1); /* not enough disk space for RIFF file */
  101.         }
  102.     /* delete and recreate file */
  103.     io->ioNamePtr = (StringPtr)filename;
  104.     io->ioVRefNum = refnum;
  105.     io->ioVersNum = 0;                /* normal version */
  106.     PBDelete(io, false);
  107.     PBCreate(io, false);
  108.     /* test for preexisting file */
  109.     if (!save_finder_info)
  110.         {
  111.         /* get file info for new file */
  112.         fparm.ioFDirIndex = 0;        /* use filename and vrefnum */
  113.         PBGetFInfo(&fparm, false);
  114.         }
  115.     /* set file type and creator for new file */
  116.     fparm.ioFlFndrInfo.fdType = 'RIFF';
  117.     fparm.ioFlFndrInfo.fdCreator = 'FSPE';
  118.     PBSetFInfo(&fparm, false);
  119.     /* open the file */
  120.     io->ioPermssn = fsWrPerm;        /* writing */
  121.     io->ioMisc = null;
  122.     io->ioResult = 1;
  123.     PBOpen(io, false);
  124.     /* restore the filename */
  125.     PtoCstr(filename);
  126.     /* test for open failed */
  127.     if (io->ioResult < 0)
  128.         return(2); /* open failed */
  129.     /* good return */
  130.     return(0);
  131.     }
  132.  
  133. /* save the RIFF file */
  134. static short save_data(refnum, filename, desired_nsamples)
  135. short refnum;
  136. char *filename;
  137. short desired_nsamples;
  138.     {
  139.     short i, j, flat, nchunks, nsamples_rounded;
  140.     long estimate, chunksize;
  141.     register unsigned char *p;
  142.     register long l;
  143.     short *huffbuff;
  144.     RIFF_header Rheader;
  145.     long save[4];
  146.     char str[32];
  147.     ioParam writeparm;
  148.     unsigned char table[256], dtable[256];
  149.  
  150.     /* allocate temporary buffer */
  151.     huffbuff = (short *)NewPtr((long)ncols * 2 + 2L);
  152.     if (huffbuff == null)
  153.         return(3); /* not enough memory */
  154.     /* generate a pessimistic disk size estimate */
  155.     nsamples_rounded = (desired_nsamples + 1) & ~1;
  156.     flat = (4 + ncols) & ~1;
  157.     switch (storage_type)
  158.         {
  159.     case st_gray:
  160.     case st_vlt:
  161.         nchunks = 1;
  162.         break;
  163.     case st_rgb:
  164.     case st_hsv:
  165.     case st_cmy:
  166.         nchunks = 3;
  167.         break;
  168.     case st_cmyk:
  169.         nchunks = 4;
  170.         break;
  171.         }
  172.     estimate = (long)flat*(long)nrows*(long)nchunks
  173.       + sizeof(RIFF_header) + nsamples_rounded;
  174.     /* open the RIFF file for writing */
  175.     i = save_open(refnum, filename, estimate, &writeparm);
  176.     /* if we got an error, clean up and exit */
  177.     if (i != 0)
  178.         {
  179.         DisposPtr(huffbuff);
  180.         return(i);
  181.         }
  182.     /* init for I/O */
  183.     if (!init_io(0L))
  184.         {
  185.         /* can't get an I/O buffer */
  186.         /* close the file */
  187.         PBClose(&writeparm, false);
  188.         DisposPtr(huffbuff);
  189.         return(3); /* not enough memory */
  190.         }
  191.     init_write(&writeparm);
  192.     /* make up a riff file header */
  193.     fillbuffer(&Rheader, sizeof(RIFF_header), 0);
  194.     Rheader.revnum = RIFF_rev1_1;
  195.     Rheader.nrows = nrows;
  196.     Rheader.ncols = ncols;
  197.     Rheader.flags = hf_transfer;
  198.     if (uncompressed)
  199.         Rheader.flags |= uncompressed;
  200.     Rheader.storage_type = storage_type;
  201.     Rheader.nsamples = desired_nsamples;
  202.     /* write out a null chunks field (and later fix it up) */
  203.     Rheader.chunks[0] = 0;
  204.     Rheader.chunks[1] = 0;
  205.     Rheader.chunks[2] = 0;
  206.     Rheader.chunks[3] = 0;
  207.     Rheader.resolution = dpi;
  208.     for (i = 0; i < 32; i++)
  209.         Rheader.reserved[i] = 0;
  210.     /* write out the riff header */
  211.     putbytes(&writeparm, &Rheader, (long)sizeof(RIFF_header));
  212.     for (i = 0; i < desired_nsamples; i++)
  213.         dtable[i] = i;
  214.     putbytes(&writeparm, dtable, (long)desired_nsamples);
  215.     /* pass 256-sample data through a table so it can be a desired number of samples */
  216.     for (i = 0; i < 256; i++)
  217.         table[i] = ((long)(transfer_table[i]) * (long)(desired_nsamples-1) + 128) / 255;
  218.     chunksize = (long)nrows * (long)ncols;
  219.     for (i = 0; i < nchunks; i++)
  220.         {
  221.         /* adjust file output alignment to be even */
  222.         flushbytes(&writeparm);
  223.         if (writeparm.ioPosOffset&1)
  224.             {
  225.             j = 0;
  226.             putbytes(&writeparm, &j, 1L); /* do even file address alignment */
  227.             }
  228.         flushbytes(&writeparm);
  229.         save[i] = writeparm.ioPosOffset;
  230.         /* run all of the data threough the table, to coerce it to a given number of samples */
  231.         for (l = 0, p = body[i]; l < chunksize; l++, p++)
  232.             *p = table[*p];
  233.         /* test for compressed output */
  234.         if (uncompressed)
  235.             putbytes(&writeparm, body[i], chunksize);
  236.         else
  237.             COMPoutput(&writeparm, body[i], huffbuff);
  238.         }
  239.     flushbytes(&writeparm);
  240.     /* free I/O buffer */
  241.     term_io();
  242.     /* go back to the beginning of the file and update the header */
  243.     for (i = 0; i < nchunks; i++)
  244.         Rheader.chunks[i] = save[i];
  245.     writeparm.ioPosMode = fsFromStart;
  246.     writeparm.ioPosOffset = 0L;
  247.     PBSetFPos(&writeparm, null);
  248.     writeparm.ioBuffer = (char *)&Rheader;
  249.     writeparm.ioReqCount = sizeof(RIFF_header);
  250.     PBWrite(&writeparm, null);
  251.     /* close the file */
  252.     PBClose(&writeparm, false);
  253.     /* flush the volume */
  254.     PBFlshVol(&writeparm, false);
  255.     DisposPtr(huffbuff);
  256.     return(0); /* no error */
  257.     }
  258.